home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 July: Mac OS SDK / Dev.CD Jul 99 SDK1.toast / Development Kits / Mac OS / QuickDraw3D 1.6 SDK / Mac SampleCode Previous / Geometry Samples- Mac / Skinny3DSample / Skinny3DSources ƒ / 3DAppSpecific.c next >
Encoding:
C/C++ Source or Header  |  1999-05-18  |  26.3 KB  |  1,036 lines  |  [TEXT/MPS ]

  1. #include <Printing.h>
  2. #include <AppleEvents.h>
  3. #include <Windows.h>
  4. #include <Fonts.h>
  5. #include <ToolUtils.h>
  6. #include <TextUtils.h>
  7. #include <LowMem.h>
  8. #include <SegLoad.h>
  9. #include <Devices.h>
  10. #include <Quickdraw.h>
  11.  
  12.  
  13. #include     "SkinnyMain.h"
  14. #include    "3DAppSpecific.h"
  15. #include     "ValueControls.h"
  16.  
  17. #include     "BoxModel.h"
  18. #include    "Cameras.h"
  19. #include     "Lights.h"
  20.  
  21. /*
  22. prototypes of QD3DFunctions called from the application (in "3DAppSpecific.h"):
  23.  
  24. OSErr    InitializeApplication(void);
  25. void    Cleanup(void);
  26. Boolean PreflightNew(void); // return TRUE if "New" will work
  27. void     DoNew(void);
  28. void     DoOpen(void);
  29. void     DoClose(void); // FrontWindow() only
  30. void     DoSave(void);
  31. void     DoSaveAs(void);
  32. void     DoPrint(void);
  33. void     DoClickInContent(EventRecord *evt, WindowPtr theWindow);
  34. void     ActivateWindow(WindowPtr newFrontWindow, Boolean active);
  35.  
  36. void    DoAppSpecificMenu(long menuNumber, long itemNumber);
  37. void     UpdateAppMenus(void);
  38.  
  39. void    DrawAppSpecificContent(WindowPtr theWindow);
  40.  
  41. */
  42. enum { windowID = 128 }; // resource ID
  43.  
  44. #define kWidth        600
  45. #define kHeight        400
  46. #define kCntrlWdth    200
  47.  
  48. typedef enum DirectionType {
  49.     none, left, right, up, down, reset
  50. } DirectionType;
  51.  
  52. // data structure tied to a window (handle into wRefCon)
  53. struct WindowInfo {
  54.     TQ3ViewObject        view;
  55.     TQ3GroupObject        model;
  56.     TQ3TransformObject    rotation;
  57.     TQ3StyleObject        interpolation;
  58.     TQ3StyleObject        backfacing;
  59.     TQ3StyleObject        fillstyle;
  60.     TQ3ShaderObject         shader;
  61.     VccPtr                vcc;
  62. };
  63. typedef struct WindowInfo WindowInfo, **WinfoH;
  64.  
  65.  
  66. // local prototypes
  67. void AddHierarchMenu(long parentMenuID, long item, long subMenuID);
  68.  
  69. static    WinfoH     Make3Dinfo(WindowPtr theWindow);
  70. static    void    Dispose3Dinfo(WinfoH wInfoH);
  71.  
  72. static    void    Draw3DPart(WinfoH wInfo);
  73. static     void    DrawDirections(void);
  74. static     void    DrawTriangle(Point p, DirectionType e);
  75. static    void    DrawControlPart(WinfoH wInfo);
  76. static    Boolean            ControlClick(Point pt, WindowPtr theWindow);
  77. static    DirectionType     RotationClick(Point pt, WindowPtr theWindow);
  78.  
  79. static    TQ3DrawContextObject    MakeDrawContext(WindowPtr theWindow);
  80.  
  81. static void SetRotation(WinfoH wInfo, DirectionType direction);
  82.  
  83. static     void     ChooseDebug(long item);
  84.  
  85. static    void    ChooseRenderer    (TQ3ViewObject view, long item);
  86.  
  87. static    void    ChooseBackfacing    (WinfoH wInfo, long item);
  88. static    void    ChooseInterpolation    (WinfoH wInfo, long item);
  89. static    void    ChooseFillStyle        (WinfoH wInfo, long item);
  90.  
  91. static    void    MakeGeometry        (WinfoH wInfo, long selector);
  92. static    void    UpdateGeometry        (WinfoH wInfo);
  93. static    void    MakeDataControl        (WinfoH wInfo);
  94. static    void    MakeNewCamera        (WinfoH wInfo, long selector);
  95. static    void    MakeCameraControl    (WinfoH wInfo);
  96. static    void    MakeLightControl    (WinfoH wInfo, long selector);
  97.  
  98. static     Boolean GoodFrontWindow(WindowPtr *theWindow, WinfoH *wInfo);
  99. void     CheckMenuItem(short menuID, short checkItem);
  100.  
  101. static     Rect    gWindowRect;
  102. static     Rect    g3DViewRect;
  103. Rect    gContrlRect; // needed to make VCC
  104.  
  105. static long curGeometry;
  106. static long curCamera;
  107. static long curLight;
  108. static long curRenderer;
  109. static long curBackfacing;
  110. static long curInterpol;
  111. static long curFillStyle;
  112.  
  113.  
  114. extern    THPrint        gPrintH;
  115. extern     CursHandle    gWatchCursor;
  116.  
  117.  
  118. //---------------------------------
  119. OSErr    InitializeApplication(void)
  120. {
  121.     MenuHandle    mh;
  122.     Handle         menuBar = GetNewMBar(128);
  123.     TQ3Status    status;
  124.     
  125.     if (!menuBar) {
  126.         return -30000;       
  127.     }
  128.     SetMenuBar(menuBar);
  129.     AppendResMenu(GetMenuHandle(mApple),'DRVR');
  130.     DrawMenuBar();
  131.     DisposeHandle(menuBar);
  132.     
  133.     AddHierarchMenu(mControl, iCamera,         mCameras);
  134.     AddHierarchMenu(mControl, iLight,         mLight);
  135.     AddHierarchMenu(mControl, iRenderer,     mRenderer);
  136.     
  137.     AddHierarchMenu(mStyle,   iBackfacing,    mBackfacing);
  138.     AddHierarchMenu(mStyle,   iInterpol,     mInterpolation);
  139.     AddHierarchMenu(mStyle,   iFillStyle,    mFillStyle);
  140.     
  141.     gPrintH = (THPrint)NewHandle(sizeof(TPrint));
  142.     if (gPrintH == nil)
  143.         return -30001;       
  144.     
  145.     status = Q3Initialize();
  146.     if ( status == kQ3Failure )
  147.         return ( -30002 );
  148.  
  149.     SetRect(&gWindowRect, 0, 0, kWidth, kHeight);
  150.     SetRect(&g3DViewRect, 0, 0, kWidth - kCntrlWdth, kHeight);
  151.     SetRect(&gContrlRect, kWidth - kCntrlWdth, 0, kWidth, kHeight);
  152.     InsetRect(&gContrlRect, 1, 1);
  153.  
  154.     return ( noErr );
  155. }
  156.  
  157. //---------------------------------------------------------------
  158. void AddHierarchMenu(long parentMenuID, long item, long subMenuID)
  159. {
  160.     MenuHandle    mh;
  161.     
  162.     mh = GetMenu(subMenuID);
  163.     InsertMenu(mh, -1);
  164.     mh = GetMenuHandle(parentMenuID);
  165.     SetItemCmd(mh, item, 0x1B);
  166.     SetItemMark(mh, item, (char)subMenuID);
  167. }
  168.  
  169.  
  170. //------------------------
  171. void    Cleanup(void)
  172. //------------------------
  173. {
  174.     TQ3Status status = Q3Exit();
  175.     // don't worry - the application heap disappears anyway,
  176.     // and we can't do anything about any failure of Q3Exit().
  177. }
  178.  
  179. //------------------------------------
  180. Boolean PreflightNew(void)
  181. {
  182.     long maxm, grow;
  183.     
  184.     maxm = MaxMem(&grow);
  185.     return (maxm > 1000000); // that's what our new QD3D window roughly needs!
  186. }
  187.  
  188. //------------------------------------
  189. void DoNew(void)
  190. {
  191.     WindowPtr    myWindow;
  192.     WinfoH        intoRefCon;
  193.     
  194.     myWindow = GetNewCWindow(windowID, nil, (WindowPtr)(-1));
  195.     if ( myWindow == nil ) {
  196.         ErrMsg("\pGetNewCWindow failed.");
  197.         return;
  198.     }
  199.     SizeWindow(myWindow, kWidth, kHeight, false);
  200.     ShowWindow(myWindow);
  201.     SetPort(myWindow);
  202.     intoRefCon = Make3Dinfo(myWindow);
  203.     if (intoRefCon != nil) {
  204.         SetWRefCon(myWindow, (long)intoRefCon );
  205.         DoAppSpecificMenu(mGeometry, iBox);
  206.     }
  207.     else {
  208.         ErrMsg("\pMake3Dinfo failed");
  209.         DisposeWindow(myWindow);
  210.     }
  211. }
  212.  
  213.  
  214. //------------------------------------
  215. void DoOpen(void)
  216. {
  217. }
  218.  
  219. //------------------------------------
  220. void DoClose(void)
  221. {
  222.     WindowPtr    theWindow;
  223.     WinfoH        theWinfo;
  224.     
  225.     if (GoodFrontWindow(&theWindow, &theWinfo))
  226.         Dispose3Dinfo(theWinfo);
  227.     CloseWindow(theWindow);
  228. }
  229.  
  230. //------------------------------------
  231. void DoSave(void)
  232. {
  233. }
  234.  
  235. //------------------------------------
  236. void DoSaveAs(void)
  237. {
  238. }
  239.  
  240. //------------------------------------
  241. void DoPrint( void )
  242. {
  243.     SysBeep(50);
  244. }
  245.  
  246. //----------------------------------------------------------------------
  247. void DoClickInContent(EventRecord *evt, WindowPtr theWindow)
  248. {
  249.     WinfoH            wInfo;
  250.     ControlHandle    ctlh;
  251.     Point            pt;
  252.     Rect            frame;
  253.     DirectionType    direction;
  254.     int                part;
  255.     
  256.     wInfo = (WinfoH)GetWRefCon(theWindow);
  257.     if (wInfo == nil) return;
  258.  
  259.     pt = evt->where;
  260.     GlobalToLocal(&pt);
  261.     if ((part = FindControl(pt, theWindow, &ctlh)) != kControlNoPart) {
  262.         /* TrackControl Goes Here */
  263.     }
  264.  
  265.     if (ControlClick(pt, theWindow)) { // our special ValueControl panel
  266.         InvalRect(&g3DViewRect);
  267.         return;
  268.     }
  269.     
  270.     if ((direction = RotationClick(pt, theWindow)) != none) {
  271.         SetRotation(wInfo, direction);
  272.         InvalRect(&g3DViewRect);
  273.     }
  274. }
  275.  
  276.  
  277. //------------------------------------
  278. static void SetRotation(WinfoH wInfo, DirectionType direction)
  279. {
  280.     TQ3Status            status;
  281.     TQ3BoundingBox        bBox;
  282.     TQ3Point3D            center, tmpPt;
  283.     TQ3Axis                axis;
  284.     float                angle;
  285.     TQ3Matrix4x4            previousMatrix, matrix, newMatrix, *tmp;
  286.     TQ3TransformObject     transform;
  287.     TQ3RotateAboutPointTransformData    tData;
  288.  
  289.     TQ3GroupObject        group;
  290.     TQ3GroupPosition        position;
  291.     TQ3ObjectType        type;
  292.     TQ3Object            theObj;
  293.     TQ3BoxData            boxData;
  294.     
  295.     if (direction == reset) {
  296.         Q3Matrix4x4_SetIdentity(&matrix);
  297.         status = Q3MatrixTransform_Set((**wInfo).rotation, &matrix);
  298.         return;
  299.     }
  300.     
  301. //    Q3View_StartBounds((**wInfo).view);
  302. //    status = Q3DisplayGroup_BoundingBox((**wInfo).model, 
  303. //                                        &bBox, 
  304. //                                         kQ3ComputeBoundsApproximate,
  305. //                                         (**wInfo).view);
  306. //    Q3View_EndBounds((**wInfo).view);
  307.     
  308.     // Cannot link with the above, for some temporary reason.
  309.     // Temporary workaround:
  310.     group = (**wInfo).model;
  311.     type = kQ3ShapeTypeGeometry;
  312.     status = Q3Group_GetFirstPositionOfType(group, type, &position);
  313.     if (status == kQ3Failure)
  314.         return;
  315.         
  316.     status = Q3Group_GetPositionObject ( group, position, &theObj);
  317.     type = Q3Geometry_GetType ( theObj );
  318.     switch (type) {
  319.         case kQ3GeometryTypeBox: 
  320.                 status = Q3Box_GetData( theObj, &boxData );
  321.                 bBox.min = boxData.origin;
  322.                 Q3Point3D_Vector3D_Add(&bBox.min, &boxData.orientation, &tmpPt);
  323.                 Q3Point3D_Vector3D_Add(&tmpPt,    &boxData.majorAxis, &tmpPt);
  324.                 Q3Point3D_Vector3D_Add(&tmpPt,       &boxData.minorAxis, &bBox.max);
  325.             break;
  326.             // add here the cases of other geometries, if required
  327.         default:
  328.             Q3Point3D_Set(&bBox.min, -1.0, -1.0, -1.0);
  329.             Q3Point3D_Set(&bBox.max, 1.0, 1.0, 1.0);
  330.             return;
  331.     }
  332.  
  333.     Q3Point3D_RRatio(&bBox.min, &bBox.max, 1.0, 1.0, ¢er); // mid-point
  334.     
  335.     status = Q3MatrixTransform_Get((**wInfo).rotation, &previousMatrix);
  336.     
  337.     if ((direction == up) || (direction == down))
  338.         axis = kQ3AxisX;
  339.     else
  340.         axis = kQ3AxisY;
  341.     if ((direction == right) || (direction == down))
  342.         angle = 0.1;
  343.     else
  344.         angle = -0.1;
  345.         
  346.     tData.axis = axis;
  347.     tData.radians = angle;
  348.     tData.about = center;
  349.     transform = Q3RotateAboutPointTransform_New(&tData);
  350.     if (transform == NULL)
  351.         return;
  352.     tmp = Q3Transform_GetMatrix(transform, &matrix);
  353.     
  354.     Q3Matrix4x4_Multiply(&previousMatrix, &matrix, &newMatrix);
  355.     status = Q3MatrixTransform_Set((**wInfo).rotation, &newMatrix);
  356.  
  357.  
  358. //------------------------------------
  359. void     ActivateWindow(WindowPtr newFrontWindow, Boolean active)
  360. {
  361.     if (active)
  362.         ;// This window is now active.  Controls should be enabled, etc.
  363.     else
  364.         ;
  365.     //    do anyting necessary to deactivate your windows here.
  366.     //    controls should be dimmed, etc.
  367. }
  368.  
  369. //------------------------------------
  370. void    DoAppSpecificMenu(long menuNumber, long item)
  371. {
  372.     WindowPtr    theWindow;
  373.     WinfoH        wInfo;
  374.     
  375.     if (menuNumber == mDebug) {
  376.         ChooseDebug(item); return;
  377.     }
  378.     
  379.     if (!GoodFrontWindow(&theWindow, &wInfo)) {
  380. //        ErrMsg("\pBad FrontWindow");
  381.         return;
  382.     }
  383.     
  384.     switch (menuNumber) {
  385.         case mGeometry: MakeGeometry(wInfo, item);
  386.                         MakeDataControl(wInfo);
  387.                         curGeometry = item;
  388.                         break;
  389.         case mControl:     if (item == iData)
  390.                         MakeDataControl(wInfo);
  391.                         break;
  392.                 
  393.         case mCameras:     if (item != curCamera) {
  394.                             MakeNewCamera(wInfo, item);
  395.                             curCamera = item;
  396.                         }
  397.                         MakeCameraControl(wInfo);
  398.                         break;
  399.         case mLight:     MakeLightControl(wInfo, item);
  400.                         curLight = item;
  401.                         break;
  402.         case mRenderer: ChooseRenderer((**wInfo).view, item);
  403.                         break;
  404.  
  405.         case mBackfacing:
  406.                         ChooseBackfacing(wInfo, item);
  407.                         curBackfacing = item;
  408.                         break;
  409.         case mInterpolation:
  410.                         ChooseInterpolation(wInfo, item);
  411.                         curInterpol = item;
  412.                         break;
  413.         case mFillStyle:
  414.                         ChooseFillStyle(wInfo, item);
  415.                         curFillStyle = item;
  416.                         break;
  417.         
  418.         default:
  419.             break;
  420.     }
  421.     InvalRect(&theWindow->portRect);
  422. }
  423.  
  424.  
  425. //------------------------------------
  426. void UpdateAppMenus(void)
  427. {
  428.     long free, maxm, grow;
  429.     Str255 freeItem = "\pFreeMem = ";
  430.     Str255 maxmItem = "\pMaxMem  = ";
  431.     Str255 s;
  432.     WindowPtr    theWindow;
  433.     WinfoH        wInfo;
  434.     MenuHandle    menu = GetMenuHandle(mDebug);
  435.     
  436.     free = FreeMem();
  437.     NumToString(free, s);
  438.     pcat(freeItem, s);
  439.     SetMenuItemText(menu, iFreeMem, freeItem);
  440.  
  441.     maxm = MaxMem(&grow);
  442.     NumToString(maxm, s);
  443.     pcat(maxmItem, s);
  444.     SetMenuItemText(menu, iMaxMem, maxmItem);
  445.     
  446.     CheckMenuItem(mGeometry, curGeometry);
  447.     CheckMenuItem(mCameras, curCamera);
  448.     CheckMenuItem(mLight, curLight);
  449.     CheckMenuItem(mRenderer, curRenderer);
  450.     CheckMenuItem(mBackfacing, curBackfacing);
  451.     CheckMenuItem(mInterpolation, curInterpol);
  452.     CheckMenuItem(mFillStyle, curFillStyle);
  453.     
  454.     if (!GoodFrontWindow(&theWindow, &wInfo)) {
  455.         DisableItem(GetMenuHandle(mGeometry), 0);
  456.         DisableItem(GetMenuHandle(mControl), 0);
  457.         DisableItem(GetMenuHandle(mStyle), 0);
  458.     }
  459.     else {
  460.         EnableItem(GetMenuHandle(mGeometry), 0);
  461.         EnableItem(GetMenuHandle(mControl), 0);
  462.         EnableItem(GetMenuHandle(mStyle), 0);
  463.     }
  464.     DrawMenuBar();
  465. }
  466.  
  467.  
  468. void CheckMenuItem(short menuID, short checkItem)
  469. {
  470.     MenuHandle    menu = GetMenuHandle(menuID);
  471.     short         n = CountMItems(menu);
  472.     short        i;
  473.     
  474.     for (i = 1; i <= n; i++)
  475.         CheckItem(menu, i, (i == checkItem));
  476. }
  477.  
  478.  
  479. //------------------------------------
  480. static    void    ChooseRenderer(TQ3ViewObject view, long item)
  481. {
  482.     TQ3Status            status;
  483.     TQ3ObjectType        rType;
  484.     TQ3RendererObject    renderer;
  485.     
  486.     switch (item) {
  487.         case iWireFrame: rType = kQ3RendererTypeWireFrame;     break;
  488.         case iZBuffer:     rType = kQ3RendererTypeInteractive;     break;
  489.     }
  490.     
  491. //    status = Q3View_SetRendererByType(view, rType);
  492. //  alternatively:
  493.     renderer = Q3Renderer_NewFromType(rType);
  494.     if (renderer == nil)
  495.         return;
  496.     status = Q3View_SetRenderer(view, renderer);
  497.     if (status == kQ3Failure )
  498.         return;
  499.         
  500.     Q3Object_Dispose(renderer) ;
  501.  
  502.     curRenderer = item;
  503. }
  504.  
  505. //------------------------------------
  506. static    void    ChooseBackfacing(WinfoH    wInfo, long item)
  507. {
  508.     TQ3Status            status;
  509.     TQ3BackfacingStyle     bfStyle;
  510.     
  511.     switch (item) {
  512.         case iBoth:     bfStyle = kQ3BackfacingStyleBoth;             break;
  513.         case iRemove:    bfStyle = kQ3BackfacingStyleRemove;     break;
  514.           case iFlip:     bfStyle = kQ3BackfacingStyleFlip;         break;
  515.     }
  516.     if ((**wInfo).backfacing != nil)
  517.         status = Q3Object_Dispose((**wInfo).backfacing);
  518.     (**wInfo).backfacing = Q3BackfacingStyle_New(bfStyle);
  519. }
  520.  
  521. //------------------------------------
  522. static    void    ChooseInterpolation(WinfoH    wInfo, long item)
  523. {
  524.     TQ3Status                status;
  525.     TQ3InterpolationStyle    ipStyle;
  526.     
  527.     switch (item) {
  528.         case iNone:     ipStyle = kQ3InterpolationStyleNone;     break;
  529.         case iVertex:    ipStyle = kQ3InterpolationStyleVertex;     break;
  530.           case iPixel:     ipStyle = kQ3InterpolationStylePixel;     break;
  531.     }
  532.     if ((**wInfo).interpolation != nil)
  533.         status = Q3Object_Dispose((**wInfo).interpolation);
  534.     (**wInfo).interpolation = Q3InterpolationStyle_New(ipStyle);
  535. }
  536.  
  537.  
  538. //------------------------------------
  539. static    void    ChooseFillStyle(WinfoH    wInfo, long item)
  540. {
  541.     TQ3Status            status;
  542.     TQ3FillStyle            flStyle;
  543.     
  544.     switch (item) {
  545.         case iFilled:     flStyle = kQ3FillStyleFilled;    break;
  546.         case iEdges:    flStyle = kQ3FillStyleEdges;    break;
  547.           case iPoints:     flStyle = kQ3FillStylePoints;    break;
  548.     }
  549.     if ((**wInfo).fillstyle != nil)
  550.         status = Q3Object_Dispose((**wInfo).fillstyle);
  551.     (**wInfo).fillstyle = Q3FillStyle_New(flStyle);
  552. }
  553.  
  554.  
  555. //------------------------------------
  556. static void ChooseDebug(long item)
  557. {    
  558. }
  559.  
  560. //////////////////////////////////////////////////////////
  561. //===========================================
  562. WinfoH Make3Dinfo(WindowPtr theWindow)
  563. {
  564.     WinfoH                wInfo;
  565.     TQ3DrawContextObject drawContext;
  566.     TQ3RendererObject    renderer;
  567.     TQ3GroupObject        lightGroup;
  568.     TQ3Matrix4x4            matrix;
  569.     TQ3Status            status;
  570.     
  571.     wInfo = (WinfoH) NewHandleClear(sizeof(WindowInfo));
  572.     if (wInfo == nil) {
  573.         ErrMsg("\pNewHandle(WindowInfo) failed");
  574.         return nil;
  575.     }
  576.     
  577.     (**wInfo).view = Q3View_New();    // Escher View
  578.     if ( (**wInfo).view == nil ) goto fail;
  579.  
  580.     // Set DrawContext, Camera, lightGroup and Renderer
  581.     drawContext = MakeDrawContext(theWindow);
  582.     if ( drawContext == nil ) goto fail;
  583.     status = Q3View_SetDrawContext((**wInfo).view, drawContext);
  584.     if ( status == kQ3Failure ) goto fail;
  585.     status = Q3Object_Dispose(drawContext); 
  586.  
  587.     MakeNewCamera(wInfo, iAspectRatio);
  588.  
  589.     lightGroup = MakeLights();
  590.     if ( lightGroup == nil ) goto fail;
  591.     status = Q3View_SetLightGroup((**wInfo).view, lightGroup);
  592.     if ( status == kQ3Failure ) goto fail;
  593.     // decrease reference count (was increased by Q3View_SetLightGroup
  594.     Q3Object_Dispose(lightGroup);
  595.     
  596.     curLight = 0; // selector for valuecontrol initially undefined
  597.     
  598.     ChooseRenderer((**wInfo).view, iWireFrame);
  599.  
  600.     (**wInfo).shader = Q3LambertIllumination_New() ;
  601.  
  602.     //    Create model to display.
  603.     (**wInfo).model = Q3OrderedDisplayGroup_New();
  604.     if ( (**wInfo).model == nil ) goto fail;
  605.  
  606.     // Set identity transform
  607.     Q3Matrix4x4_SetIdentity(&matrix);
  608.     (**wInfo).rotation = Q3MatrixTransform_New(&matrix);
  609.  
  610.     //    Configure the drawing styles.
  611.     ChooseInterpolation    (wInfo, iNone);        curInterpol     = iNone;
  612.     ChooseBackfacing    (wInfo, iBoth);        curBackfacing     = iBoth;
  613.     ChooseFillStyle        (wInfo, iFilled);    curFillStyle     = iFilled;
  614.  
  615.     return wInfo;
  616.     
  617. fail:
  618.     Dispose3Dinfo(wInfo);
  619.     return nil;
  620. }
  621.  
  622. // ---------------------------------------------------------------------
  623. void    Dispose3Dinfo(WinfoH wInfoH)
  624. {
  625.     TQ3Status    status;
  626.     
  627.     if (wInfoH == nil) return;
  628.     if ((**wInfoH).view != nil)
  629.         status = Q3Object_Dispose((**wInfoH).view);
  630.     if ((**wInfoH).model != nil) {
  631.         // need to dispose properly of everything ...
  632.         status = Q3Object_Dispose((**wInfoH).model);
  633.     }
  634.     if ((**wInfoH).interpolation != nil)
  635.         status = Q3Object_Dispose((**wInfoH).interpolation);
  636.     if ((**wInfoH).backfacing != nil)
  637.         status = Q3Object_Dispose((**wInfoH).backfacing);
  638.     if ((**wInfoH).fillstyle != nil)
  639.         status = Q3Object_Dispose((**wInfoH).fillstyle);
  640.     DisposeHandle((Handle) wInfoH);
  641. }
  642.  
  643.  
  644. // --------------------------------------------------------------------
  645. TQ3DrawContextObject MakeDrawContext(WindowPtr theWindow)
  646. {
  647.     TQ3DrawContextData        drawContextData;
  648.     TQ3MacDrawContextData    macDrawContextData;
  649.     TQ3ColorARGB            ClearColor;
  650.     
  651.     //    Set the background color.
  652.     ClearColor.a = 1.0; /* Solid alpha */
  653.     ClearColor.r = 1.0;
  654.     ClearColor.g = 1.0;
  655.     ClearColor.b = 1.0;
  656.     
  657.     //    Fill in draw context data.
  658.     drawContextData.clearImageMethod = kQ3ClearMethodWithColor;
  659.     drawContextData.clearImageColor = ClearColor;
  660.     drawContextData.pane.min.x = (theWindow->portRect).left;
  661.     drawContextData.pane.max.x = (theWindow->portRect).right;
  662.     drawContextData.pane.min.y = (theWindow->portRect).top;
  663.     drawContextData.pane.max.y = (theWindow->portRect).bottom;
  664.     drawContextData.paneState = kQ3True;
  665.     drawContextData.maskState = kQ3False;
  666.     drawContextData.doubleBufferState = kQ3True;
  667.  
  668.     macDrawContextData.drawContextData = drawContextData;
  669.     macDrawContextData.window = (CWindowPtr) theWindow;
  670.     macDrawContextData.library = kQ3Mac2DLibraryQuickDraw;
  671.     macDrawContextData.viewPort = nil;
  672.     macDrawContextData.grafPort = (CGrafPtr) theWindow;
  673.  
  674.     //    Create draw context.
  675.     return  Q3MacDrawContext_New(&macDrawContextData);
  676.     
  677. }
  678.  
  679. //----------------------------------------------------------------------------------
  680. void    DrawAppSpecificContent(WindowPtr theWindow)
  681. {
  682.     WinfoH wInfo;
  683.     
  684.     wInfo = (WinfoH)GetWRefCon(theWindow);
  685.     if (wInfo == nil)
  686.         return;
  687.     Draw3DPart(wInfo);
  688.     DrawControlPart(wInfo);
  689. }
  690.  
  691. //----------------------------------------------------------------------------------
  692. static void Draw3DPart(WinfoH wInfo)
  693. {
  694.     TQ3Status                status;
  695.     //TQ3DrawContextObject        myDrawContext;
  696.     TQ3ViewStatus            myViewStatus;
  697.     WindowInfo                wI = **wInfo;
  698.     TQ3RendererObject        myRenderer ;
  699.     
  700.     status = Q3View_StartRendering(wI.view);
  701.     if ( status == kQ3Failure ) goto bail;
  702.     
  703.     if (curInterpol == iPixel)
  704.         SetCursor(*gWatchCursor);
  705.  
  706.     do {
  707.         if (curFillStyle == iFilled) {
  708.             status = Q3Shader_Submit(wI.shader, wI.view);
  709.             if ( status == kQ3Failure ) goto bail;
  710.         }
  711.         status = Q3Style_Submit(wI.interpolation, wI.view);
  712.         if ( status == kQ3Failure ) goto bail;
  713.         status = Q3Style_Submit(wI.backfacing, wI.view);
  714.         if ( status == kQ3Failure ) goto bail;
  715.         status = Q3Style_Submit(wI.fillstyle, wI.view);
  716.         if ( status == kQ3Failure ) goto bail;
  717.         status = Q3Transform_Submit( wI.rotation, wI.view);
  718.         if ( status == kQ3Failure ) goto bail;
  719.         status = Q3DisplayGroup_Submit(wI.model, wI.view);
  720.         if ( status == kQ3Failure ) goto bail;
  721.         myViewStatus = Q3View_EndRendering(wI.view);
  722.     } while ( myViewStatus == kQ3ViewStatusRetraverse );
  723.     
  724.     // get the renderer from the view
  725.     status = Q3View_GetRenderer( wI.view, &myRenderer ) ;
  726.     if ( status == kQ3Failure ) goto bail;
  727.             
  728.     // call sync 'cos we are going to draw over it.  This is needed since if we are running with
  729.     // hardware (which is asynchronous) then we need to ensure that the HW has finished drawing
  730.     // before drawing the controls.
  731.     Q3View_Sync( wI.view ) ;
  732.     
  733.     status = Q3Object_Dispose(myRenderer); 
  734.     
  735.     DrawDirections();
  736.     
  737.     InitCursor();
  738.     return;
  739.  
  740. bail:
  741.     SysBeep(50);
  742. }
  743.  
  744. //------------------------------------
  745. static     void    DrawDirections(void)
  746. {
  747.     Point    p;
  748.     short     d = 4; // distance from border
  749.     
  750.     p.h = (g3DViewRect.right - g3DViewRect.left) / 2;
  751.     p.v = g3DViewRect.top + d;
  752.     DrawTriangle(p, up);
  753.     p.v = g3DViewRect.bottom - d;
  754.     DrawTriangle(p, down);
  755.     p.h = g3DViewRect.left + d; 
  756.     p.v = (g3DViewRect.bottom - g3DViewRect.top) / 2;
  757.     DrawTriangle(p, left);
  758.     p.h = g3DViewRect.right - d;
  759.     DrawTriangle(p, right);
  760.     MoveTo(g3DViewRect.right - 20, g3DViewRect.top + 14);
  761.     TextFont(geneva); TextSize(12); TextFace(0);
  762.     DrawString("\p(R)");
  763. }
  764.  
  765. //------------------------------------
  766. static     void    DrawTriangle(Point p, DirectionType e)
  767. {
  768. #define        k   10 
  769.  
  770.     short    x1, y1, x2, y2, x3, y3;
  771.     
  772.     switch (e) {
  773.     case up:    x1 = y1 = x3 = k; y3 = -k; x2 = - k - k; y2 = 0;    break;
  774.     case down:    x1 = y1 = x3 = -k; y3 = k; x2 = k + k; y2 = 0;        break;
  775.     case left:    x1 = y1 = y3 = k; x3 = -k; x2 = 0; y2 = - k - k;    break;
  776.     case right: x1 = y1 = y3 = -k; x3 = k; x2 = 0; y2 = k + k;        break;
  777.     }
  778.         
  779.     MoveTo(p.h, p.v);
  780.     Line(x1, y1); Line(x2, y2); Line(x3, y3);
  781. }
  782.  
  783. //------------------------------------
  784. static    void    DrawControlPart(WinfoH wInfo)
  785. {
  786.     EraseRect(&gContrlRect);
  787.     FrameRect(&gContrlRect);
  788.     if ((**wInfo).vcc != nil)
  789.         DrawVCluster((**wInfo).vcc);
  790. }
  791.  
  792.  
  793. //------------------------------------
  794. static Boolean    ControlClick(Point pt, WindowPtr theWindow)
  795. {
  796.     WinfoH        wInfo;
  797.     OSType        tag;
  798.     TQ3Status    status;
  799.     
  800.     wInfo = (WinfoH)GetWRefCon(theWindow);
  801.     if (wInfo == nil)
  802.         return false;
  803.  
  804.     if ( TakeHit(pt, (**wInfo).vcc) ) {
  805.         tag = GetIdTag((**wInfo).vcc);
  806.         switch (tag) {
  807.             case kQ3GeometryTypeBox:
  808.                     UpdateGeometry(wInfo);
  809.                 break;
  810.                 
  811.             case kQ3CameraTypeOrthographic:
  812.             case kQ3CameraTypeViewPlane:
  813.             case kQ3CameraTypeViewAngleAspect:
  814.                 {
  815.                     TQ3CameraObject    camera;
  816.                 
  817.                     status = Q3View_GetCamera((**wInfo).view, &camera);
  818.                     VCCtoCameraData((**wInfo).vcc, camera);
  819.                     status = Q3View_SetCamera((**wInfo).view, camera);
  820.                     status = Q3Object_Dispose(camera); 
  821.                 }
  822.                 break;
  823.  
  824.             case kQ3LightTypeAmbient:
  825.             case kQ3LightTypeDirectional:
  826.             case kQ3LightTypePoint:
  827.             case kQ3LightTypeSpot:
  828.                 {
  829.                     TQ3CameraObject    camera;
  830.                     TQ3GroupObject    lightGroup;
  831.  
  832.                     status = Q3View_GetLightGroup((**wInfo).view, &lightGroup);
  833.                     VCCtoLight((**wInfo).vcc, lightGroup);                
  834.                 }
  835.                 break;
  836.  
  837.         // add here other types of valueControls
  838.         }
  839.         return true;
  840.     }
  841.     else
  842.         return false;
  843. }
  844.  
  845.  
  846. //----------------------------------------------------------------------------------
  847. static    DirectionType  RotationClick(Point pt, WindowPtr theWindow)
  848. {
  849.     Rect    leftRect, rightRect, upRect, downRect, resetRect;
  850.     Rect    r = g3DViewRect;  // shorthand notation
  851.     short     h3 = (g3DViewRect.right - g3DViewRect.left) / 3;
  852.     short     v3 = (g3DViewRect.bottom - g3DViewRect.top) / 3;
  853.     
  854.     SetRect(&leftRect,     r.left,          r.top + v3,      r.left + h3,   r.bottom - v3);
  855.     SetRect(&rightRect, r.right - h3, r.top + v3,      r.right,         r.bottom - v3);
  856.     SetRect(&upRect,     r.left + h3,  r.top,          r.right - h3,  r.top + v3);
  857.     SetRect(&downRect,     r.left + h3,  r.bottom - v3, r.right - h3,  r.bottom);
  858.     SetRect(&resetRect, r.right - 32,  r.top, r.right,  r.top + 32);
  859.     if (PtInRect(pt, &leftRect))    return left;
  860.     if (PtInRect(pt, &rightRect))     return right;
  861.     if (PtInRect(pt, &upRect))        return up;
  862.     if (PtInRect(pt, &downRect))    return down;
  863.     if (PtInRect(pt, &resetRect))    return reset;
  864.     return none;
  865. }
  866.  
  867. //----------------------------------------------------------------------------------
  868. void    MakeGeometry(WinfoH wInfo, long selector)
  869. {
  870.     if ((**wInfo).model != NULL) {
  871.     // ••• need to release memory allocated in attributes!
  872.         Q3Group_EmptyObjects((**wInfo).model);
  873.         Q3Object_Dispose((**wInfo).model);
  874.     }
  875.     
  876.     switch (selector) {
  877.         case iBox:     (**wInfo).model = MakeBox();
  878.             break;
  879.         case iEllipsoid:// aGeometry = MakeEllipsoid();
  880.                     SysBeep(10);
  881.             break;
  882.         case iCylinder: // aGeometry = MakeCylinder();
  883.                     SysBeep(10);
  884.             break;
  885.         case iCone:     // aGeometry = MakeCone();
  886.                     SysBeep(10);
  887.             break;
  888.         case iTorus:     // aGeometry = MakeTorus();
  889.                     SysBeep(10);
  890.             break;
  891.  
  892.         default:
  893.             break;
  894.     }
  895. }
  896.  
  897.  
  898. //----------------------------------------------------------------------------------
  899. void    MakeDataControl(WinfoH wInfo)
  900. {
  901.     TQ3GroupObject        group;
  902.     TQ3GroupPosition        position;
  903.     TQ3ObjectType        type;
  904.     TQ3Status            status;
  905.     TQ3Object            theObj;
  906.  
  907.     if ((**wInfo).vcc != nil) {
  908.         DisposeVCluster((**wInfo).vcc);
  909.         (**wInfo).vcc = nil;
  910.     }
  911.     
  912.     group = (**wInfo).model;
  913.     type = kQ3ShapeTypeGeometry;
  914.     status = Q3Group_GetFirstPositionOfType(group, type, &position);
  915.     if (status == kQ3Failure)
  916.         return;
  917.         
  918.     status = Q3Group_GetPositionObject ( group, position, &theObj);
  919.     type = Q3Geometry_GetType ( theObj );
  920.     switch (type) {
  921.         case kQ3GeometryTypeBox: 
  922.             (**wInfo).vcc = BoxDataToVCC(theObj);
  923.             break;
  924.             // add here data of other geometries
  925.         default:
  926.             return;
  927.     }
  928. }
  929.  
  930.  
  931. //----------------------------------------------------------------------------------
  932. static void MakeNewCamera (WinfoH wInfo, long selector)
  933. {
  934.     TQ3CameraObject        camera;
  935.     TQ3Status            status;
  936.     
  937.     camera = MakeCamera(selector);
  938.     status = Q3View_SetCamera((**wInfo).view, camera);
  939.     if ( status != kQ3Success )
  940.         ErrMsg("\pSetCamera failed");
  941.     status = Q3Object_Dispose(camera); 
  942.     curCamera = selector;
  943. }
  944.  
  945.  
  946. //----------------------------------------------------------------------------------
  947. static void MakeCameraControl(WinfoH wInfo)
  948. {
  949.     TQ3CameraObject    camera;
  950.     TQ3Status        status;
  951.  
  952.     if ((**wInfo).vcc != nil) {
  953.         DisposeVCluster((**wInfo).vcc);
  954.         (**wInfo).vcc = nil;
  955.     }
  956.     status = Q3View_GetCamera((**wInfo).view, &camera);
  957.     if (status != kQ3Success)
  958.         return;
  959.     (**wInfo).vcc = CameraDataToVCC(camera);
  960.     status = Q3Object_Dispose(camera); 
  961. }
  962.  
  963.  
  964. //----------------------------------------------------------------------------------
  965. static void MakeLightControl (WinfoH wInfo, long selector)
  966. {
  967.     TQ3Status        status;
  968.     TQ3GroupObject    lightGroup;
  969.         
  970.     if ((**wInfo).vcc != nil) {
  971.         DisposeVCluster((**wInfo).vcc);
  972.         (**wInfo).vcc = nil;
  973.     }
  974.     status = Q3View_GetLightGroup((**wInfo).view, &lightGroup);
  975.     (**wInfo).vcc = LightToVCC(lightGroup, selector);
  976. }
  977.  
  978.  
  979. //----------------------------------------------------------------------------------
  980. static void    UpdateGeometry(WinfoH wInfo)
  981. {
  982.     TQ3GroupObject        group;
  983.     TQ3GroupPosition        position;
  984.     TQ3ObjectType        type;
  985.     TQ3Status            status;
  986.     TQ3Object            theObj;
  987.     
  988.     group = (**wInfo).model;
  989.     type = kQ3ShapeTypeGeometry;
  990.     status = Q3Group_GetFirstPositionOfType(group, type, &position);
  991.     if (status == kQ3Failure)
  992.         return;
  993.         
  994.     status = Q3Group_GetPositionObject( group, position, &theObj);
  995.     type = Q3Geometry_GetType( theObj );
  996.     switch (type) {
  997.         case kQ3GeometryTypeBox: {
  998.                 TQ3BoxData    boxData;
  999.                 status = Q3Box_GetData(theObj, &boxData);
  1000.                 if (status == kQ3Failure)
  1001.                     return; 
  1002.                 VCCtoBoxData((**wInfo).vcc, &boxData);
  1003.                 status = Q3Box_SetData(theObj, &boxData);
  1004.             //    Q3Box_EmptyData(&boxData);
  1005.             }
  1006.             break;
  1007.             // add here data of other geometries
  1008.         default:
  1009.             return;
  1010.     }
  1011.     status = Q3Group_SetPositionObject( group, position, theObj);
  1012.     status = Q3Object_Dispose(theObj); 
  1013. }
  1014.  
  1015.  
  1016.  
  1017. //----------------------------------------------------------------------------------
  1018. static Boolean GoodFrontWindow(WindowPtr *theWindow, WinfoH *wInfo)
  1019. {
  1020.     WindowPtr    w;
  1021.     Boolean        isGood = true;
  1022.     
  1023.     w = FrontWindow();
  1024.     if (w == nil) // menu item should be disabled!
  1025.         isGood = false;
  1026.     if ( (*(WindowRecord *)w).windowKind != userKind )
  1027.         isGood = false;
  1028.     *theWindow = w;
  1029.     *wInfo = (WinfoH)GetWRefCon(w);
  1030. }
  1031.  
  1032.  
  1033.  
  1034.  
  1035.